package site.isscloud.framework.config;

import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import site.isscloud.framework.config.properties.MqttProperties;
import site.isscloud.framework.mqtt.MqttMessageHandler;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * MQTT配置类
 */
@Configuration
@ConditionalOnProperty(name = "mqtt.enabled", havingValue = "true")
public class MqttConfig {

    private static final Logger log = LoggerFactory.getLogger(MqttConfig.class);

    @Autowired
    private MqttProperties mqttProperties;

    private MqttMessageHandler messageHandler;
    private MqttClient mqttClient;

    /**
     * 设置消息处理器
     */
    public void setMessageHandler(MqttMessageHandler messageHandler) {
        this.messageHandler = messageHandler;
        log.info("MQTT消息处理器设置完成");
    }

    /**
     * 创建MQTT客户端连接
     */
    @Bean
    public MqttClient mqttClient() {
        // 检查是否启用MQTT
        if (!mqttProperties.isEnabled()) {
            log.info("MQTT功能未启用，跳过连接");
            return null;
        }

        // 添加配置调试信息
        log.info("MQTT连接配置 - cleanSession: {}, brokerUrl: {}, clientId: {}",
                mqttProperties.isCleanSession(),
                mqttProperties.getBrokerUrl(),
                mqttProperties.getClientId());

        try {
            MemoryPersistence persistence = new MemoryPersistence();
            mqttClient = new MqttClient(
                    mqttProperties.getBrokerUrl(),
                    mqttProperties.getClientId(),
                    persistence
            );

            MqttConnectOptions options = new MqttConnectOptions();
//            options.setCleanSession(mqttProperties.isCleanSession());
            options.setCleanSession(true);
            options.setConnectionTimeout(mqttProperties.getConnectionTimeout());
            options.setKeepAliveInterval(mqttProperties.getKeepAliveInterval());
            options.setAutomaticReconnect(mqttProperties.isAutomaticReconnect());
            options.setMaxInflight(mqttProperties.getMaxInflight());

            String username = mqttProperties.getUsername();
            String password = mqttProperties.getPassword();
            if (username != null && !username.isEmpty()) {
                options.setUserName(username);
            }
            if (password != null && !password.isEmpty()) {
                options.setPassword(password.toCharArray());
            }

            mqttClient.setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable cause) {
                    log.error("MQTT连接断开: {}", cause.getMessage());
                    if (mqttProperties.isAutomaticReconnect()) {
                        log.info("尝试自动重连...");
                        try {
                            Thread.sleep(5000);
                            if (!mqttClient.isConnected()) {
                                mqttClient.connect();
                                subscribeBusinessTopics();
                            }
                        } catch (Exception e) {
                            log.error("自动重连失败", e);
                        }
                    }
                }

                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    // 明确使用UTF-8解码，解决乱码问题
                    String payload = new String(message.getPayload(), StandardCharsets.UTF_8);
                    log.info("收到MQTT消息 - 主题: {}, 内容: {}, QoS: {}", topic, payload, message.getQos());

                    if (messageHandler != null) {
                        messageHandler.handleMessage(topic, payload, message.getQos());
                    } else {
                        log.warn("未设置MQTT消息处理器，无法处理消息");
                    }
                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {
                    try {
                        log.debug("消息发布完成 - 消息ID: {}", token.getMessageId());
                    } catch (Exception e) {
                        log.error("获取消息ID失败", e);
                    }
                }
            });

            mqttClient.connect(options);
            log.info("MQTT连接成功 - Broker: {}, ClientId: {}",
                    mqttProperties.getBrokerUrl(), mqttProperties.getClientId());

            // 订阅业务主题
            subscribeBusinessTopics();

            return mqttClient;

        } catch (MqttException e) {
            log.error("MQTT连接失败: {}", e.getMessage(), e);
            throw new RuntimeException("MQTT连接失败", e);
        }
    }

    /**
     * 订阅业务相关的主题
     */
    private void subscribeBusinessTopics() {
        // 从配置中获取主题和QoS
        String realtimeTopic = mqttProperties.getRealtimeTopic();
        String alarmTopic = mqttProperties.getAlarmTopic();
        int realtimeQos = mqttProperties.getRealtimeQos();
        int alarmQos = mqttProperties.getAlarmQos();

        // 实时数据订阅
        subscribe(realtimeTopic, realtimeQos);

        // 告警数据订阅
        subscribe(alarmTopic, alarmQos);

        log.info("MQTT主题订阅完成 - 实时数据: {} (QoS {}), 告警数据: {} (QoS {})",
                realtimeTopic, realtimeQos, alarmTopic, alarmQos);
    }

    /**
     * 订阅主题
     */
    public void subscribe(String topic, int qos) {
        try {
            if (mqttClient != null && mqttClient.isConnected()) {
                mqttClient.subscribe(topic, qos);
                log.info("订阅主题成功 - 主题: {}, QoS: {}", topic, qos);
            } else {
                log.warn("MQTT客户端未连接，无法订阅主题");
            }
        } catch (MqttException e) {
            log.error("订阅主题失败 - 主题: {}", topic, e);
        }
    }

    /**
     * 取消订阅
     */
    public void unsubscribe(String topic) {
        try {
            if (mqttClient != null && mqttClient.isConnected()) {
                mqttClient.unsubscribe(topic);
                log.info("取消订阅主题: {}", topic);
            }
        } catch (MqttException e) {
            log.error("取消订阅主题失败: {}", topic, e);
        }
    }

    /**
     * 发布消息
     */
    public boolean publish(String topic, String message, int qos) {
        // 检查MQTT是否启用
        if (!mqttProperties.isEnabled() || mqttClient == null) {
            log.warn("MQTT功能未启用或客户端未初始化，无法发布消息");
            return false;
        }

        try {
            if (mqttClient.isConnected()) {
                MqttMessage mqttMessage = new MqttMessage();
                // 明确使用UTF-8编码，解决乱码问题
                mqttMessage.setPayload(message.getBytes(StandardCharsets.UTF_8));
                mqttMessage.setQos(qos);
                mqttMessage.setRetained(false);

                mqttClient.publish(topic, mqttMessage);
                log.debug("发布消息成功 - 主题: {}, 内容: {}, QoS: {}", topic, message, qos);
                return true;
            } else {
                log.warn("MQTT客户端未连接，无法发布消息");
                return false;
            }
        } catch (MqttException e) {
            log.error("发布消息失败 - 主题: {}, 内容: {}", topic, message, e);
            return false;
        }
    }

    /**
     * 发布消息到默认主题
     */
    public boolean publishToDefaultTopic(String message, int qos) {
        return publish(mqttProperties.getRealtimeTopic(), message, qos);
    }

    public boolean isConnected() {
        return mqttClient != null && mqttClient.isConnected();
    }

    public boolean isEnabled() {
        return mqttProperties.isEnabled();
    }

    // Getter methods
    public String getBrokerUrl() { return mqttProperties.getBrokerUrl(); }
    public String getClientId() { return mqttProperties.getClientId(); }
    public String getDefaultTopic() { return mqttProperties.getRealtimeTopic(); }
    public Map<String, Integer> getQos() { return mqttProperties.getQos(); }
}